package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.message.domain.entity.PushSetEntity;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.AddressEnum;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.help.subform.TransferSubFormHelper;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.domain.entity.LabelEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.message.constant.CluePushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.model.PushSetModel;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.AutoClueAssignmentRabbitMqDTO;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.pushset.CluePushSet;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ClueAutoAllocationEntity;
import com.xbongbong.saas.domain.entity.ClueRuleEntity;
import com.xbongbong.saas.domain.entity.ClueUserEntity;
import com.xbongbong.saas.domain.entity.TransferBackRuleSeniorEntity;
import com.xbongbong.saas.enums.ClueAutoDistributTypeEnum;
import com.xbongbong.saas.enums.ClueRuleEnum;
import com.xbongbong.saas.enums.ClueSeniorRuleTypeEnum;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.dictionary.PublicEnum;
import com.xbongbong.saas.enums.subform.ClueTeamEnum;
import com.xbongbong.saas.help.PublicSeniorRuleHelp;
import com.xbongbong.saas.model.ClueAutoAllocationModel;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.ClueRuleModel;
import com.xbongbong.saas.model.ClueUserModel;
import com.xbongbong.saas.model.LabelModel;
import com.xbongbong.saas.model.TransferBackRuleSeniorModel;
import com.xbongbong.saas.service.AutoClueAssignmentRabbitService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author long
 * @version v1.0
 * @date 2021/1/18 11:07
 * @since v1.0
 */
@Service("autoClueAssignmentRabbitService")
public class AutoClueAssignmentRabbitServiceImpl implements AutoClueAssignmentRabbitService {

    private static final Logger LOG = LoggerFactory.getLogger(AutoClueAssignmentRabbitServiceImpl.class);

    private static final List<Integer> userFieldList = Arrays.asList(FieldTypeEnum.USER.getType(), FieldTypeEnum.USER_GROUP.getType(),
            FieldTypeEnum.CREATORID.getType(), FieldTypeEnum.OWNERID.getType());

    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private ClueAutoAllocationModel clueAutoAllocationModel;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private ClueUserModel clueUserModel;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private ClueModel clueModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private UserModel userModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private ClueRuleModel clueRuleModel;
    @Resource
    private PushSetModel pushSetModel;
    @Resource
    private LabelModel labelModel;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private TransferSubFormHelper transferSubFormHelper;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PublicSeniorRuleHelp publicSeniorRuleHelp;
    @Resource
    private TransferBackRuleSeniorModel transferBackRuleSeniorModel;

    @Override
    public void autoClueAssignment(AutoClueAssignmentRabbitMqDTO autoClueAssignmentRabbitMqDTO) throws XbbException{
        String corpid = autoClueAssignmentRabbitMqDTO.getCorpid();
        try {
            LOG.info("是否需要更新自动分配规则autoClueAssignment：corpid:{}--dataid:{}",corpid,autoClueAssignmentRabbitMqDTO.getDataIds());
            boolean publicPoolSeniorModel = commonHelp.isCluePublicPoolSeniorModel(corpid);
            Integer modelType = BasicConstant.ONE;
            String configAlias = CompanyConfigEnum.AUTOMATICALLY_ASSIGNED.getAlias();
            if (publicPoolSeniorModel){
                modelType = BasicConstant.TWO;
                configAlias = CompanyConfigEnum.AUTOMATICALLY_ASSIGNED_SENIOR.getAlias();
            }

            CompanyConfigEntity configEntity = companyConfigModel.getByConfigAlias(configAlias, corpid);
            if (Objects.isNull(configEntity) || !Objects.equals(configEntity.getConfigValue(), "1")) {
                return;
            }
            // 标准版不能进行线索自动分配
            Boolean standardWithFeeType = packageHelp.isStandardWithFeeType(corpid);
            if (standardWithFeeType) {
                return;
            }
            List<Long> dataIds = autoClueAssignmentRabbitMqDTO.getDataIds();
            PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(autoClueAssignmentRabbitMqDTO.getFormId(), corpid);
            if (Objects.isNull(paasFormEntityExt)) {
                return;
            }


            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            //区分公海高级模式
            param.put("modelType",modelType);
            param.put("del", 0);
            // 过滤未启用的表单对应的分配规则
            param.put("formId", paasFormEntityExt.getId());
            param.put("orderByStr", "priority asc");
            List<ClueAutoAllocationEntity> entitys = clueAutoAllocationModel.findEntitys(param);

            if (CollectionsUtil.isEmpty(entitys)) {
                return;
            }
            Long todayInt = DateTimeUtil.getTodayInt();
            //标准模式和高级模式获取最大线索数来源不同
            ClueRuleEntity maxRule = new ClueRuleEntity();
            if(publicPoolSeniorModel){
                List<TransferBackRuleSeniorEntity> seniorEntityList = transferBackRuleSeniorModel.getTransferBackRuleByType(corpid,paasFormEntityExt.getId(),XbbRefTypeEnum.CLUE.getCode(),Arrays.asList(ClueSeniorRuleTypeEnum.MAX_CLUE_NUM_RULE.getCode()),BasicConstant.ONE);
                if(CollectionsUtil.isNotEmpty(seniorEntityList)){
                    publicSeniorRuleHelp.copyRuleEntity(seniorEntityList.get(0),null,maxRule,XbbRefTypeEnum.CLUE.getCode());
                }
            }else {
                // TODO 缓存最大线索规则
                maxRule = clueRuleModel.getByRuleType(ClueRuleEnum.MAX_CLUE_NUM_RULE.getCode(), corpid);
            }
            Set<String> userIdIn = new HashSet<>();
            boolean hasOwnerFilter = false;
            Iterator<ClueAutoAllocationEntity> iterator = entitys.iterator();
            while (iterator.hasNext()) {
                ClueAutoAllocationEntity next = iterator.next();
                // 分配时间间隔
                Long num = StringUtil.StringToLong(paasRedisHelper.getValue(RedisPrefixConstant.CLUE_AUTO_ALLOT, corpid + "_" + next.getId()), null);
                Integer allocationInterval = next.getAllocationInterval();
                if (Objects.nonNull(num) && !Objects.equals(todayInt, DateTimeUtil.getTodayInt(num))) {
                    // 不符合执行时间
                    iterator.remove();
                } else {
                    if (allocationInterval > 0) {
                        // 隔allocationInterval天，隔一天，是加两天的时间戳
                        Integer time = (allocationInterval +1) * TimeConstant.SECONDS_PER_DAY;
                        Long timeLong = todayInt + time;
                        paasRedisHelper.setValue(RedisPrefixConstant.CLUE_AUTO_ALLOT, corpid + "_" + next.getId(), timeLong, time);
                    }
                    JSONArray jsonArray = next.getJsonData();
                    for(Object obj : jsonArray) {
                        JSONObject conditionObj = (JSONObject) obj;
                        List<Object> valueList = new ArrayList<>();
                        if (conditionObj.get("value") instanceof List) {
                            valueList = conditionObj.getJSONArray("value");
                        }
                        if(Objects.isNull(valueList) || valueList.isEmpty()) {
                            continue;
                        }
                        Integer fieldType = conditionObj.getInteger("fieldType");
                        if(userFieldList.contains(fieldType)) {
                            if (Objects.equals(fieldType, FieldTypeEnum.OWNERID.getType())) {
                                hasOwnerFilter = true;
                            }
                            for(Object userId: valueList) {
                                String userIdStr = userId.toString();
                                if (StringUtil.isEmpty(userIdStr)) {
                                    continue;
                                }
                                userIdIn.add(userIdStr);
                            }
                        }

                    }
                    JSONArray allocationSurplus = next.getAllocationSurplus();
                    if (Objects.nonNull(allocationSurplus) && !allocationSurplus.isEmpty()) {
                        for (int i = 0; i < allocationSurplus.size(); i++) {
                            JSONObject object = allocationSurplus.getJSONObject(i);
                            String userId = object.getString("user");
                            if (StringUtil.isNotEmpty(userId)) {
                                userIdIn.add(userId);
                            }
                        }
                    }
                    JSONArray allocationValue = next.getAllocationValue();
                    Integer allocationType = next.getAllocationType();
                    if (Objects.nonNull(allocationValue) &&  !allocationValue.isEmpty()) {
                        Map<Integer, Map<List<String>, Integer>> allotValueMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        List<Integer> numList = new ArrayList<>();
                        for (Object obj : allocationValue) {
                            JSONObject jsonObject = (JSONObject) obj;
                            List<Object> userIds = jsonObject.getJSONArray("user");
                            Integer allotNum = jsonObject.getInteger("num");
                            if (Objects.nonNull(allotNum)) {
                                numList.add(allotNum);
                            }
                            if(CollectionsUtil.isNotEmpty(userIds)) {
                                List<String> userIdList = new ArrayList<>();
                                for (Object userId : userIds) {
                                    userIdIn.add(userId.toString());
                                    userIdList.add(userId.toString());
                                }
                                Map<List<String>, Integer> stringIntegerMap = allotValueMap.getOrDefault(allocationType, new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY));
                                // 每个用户的数量比例
                                stringIntegerMap.put(userIdList, allotNum);
                                // 分配类型为key的每个用户的数量
                                allotValueMap.put(allocationType, stringIntegerMap);
                            }
                        }
                        if (!allotValueMap.isEmpty()) {
                            // TODO 可优化，避免三层循环
                            next.setAllocationValueMap(allotValueMap);
                        }
                        next.setNumList(numList);

                    }
                }

            }
            if (CollectionsUtil.isEmpty(entitys)) {
                return;
            }
            if (CollectionsUtil.isEmpty(userIdIn)) {
                return;
            }
            Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("corpid", corpid);
            map.put("del", 0);
            map.put("userIdIn", userIdIn);
            map.put("start", 0);
            map.put("pageNum", BasicConstant.MAX_USER_COUNT);
            map.put("columns", "corpid,user_id,name,role_ids,department");
            List<UserEntity> userList = userModel.findEntitys(map);
            if (CollectionsUtil.isEmpty(userList)) {
                return;
            }
            Map<String, UserEntity> userEntityMap = new HashMap<>(userList.size());
            for (UserEntity userEntity : userList) {
                userEntityMap.put(userEntity.getUserId(), userEntity);
            }

            boolean pushMessage = false;
            CluePushSet cluePushSet = new CluePushSet();
            PushSetEntity pushSetEntity = cluePushSet.getPushSet(corpid, PushTypeEnum.CLUE_DISTRIBUTION_PUSH.getSubCode(), pushSetModel);
            if (Objects.equals(pushSetEntity.getEnable(), 1)) {
                pushMessage = true;
                /*String pushObjectStr = pushSetEntity.getPushObject();
                JSONObject pushObject = JsonHelperUtil.parseObject(pushObjectStr);
                String typeStr = pushObject.getString("type");
                JSONArray typeJsonArray = JsonHelperUtil.parseArray(typeStr);
                for (Object object : typeJsonArray) {
                    JSONObject jsonObject = (JSONObject) object;
                    Integer enable = jsonObject.getInteger("enable");
                    if (Objects.equals(enable, 1)) {
                        String alias = jsonObject.getString("alias");
                        if (Objects.equals(alias, PushObjectTypeEnum.MAINUSER.getAlias())) {
                            pushMessage = true;
                            break;
                        }
                    }
                }*/
            }

            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_SAAS_CLUE;
            List<PaasFormDataEntityExt> resultList;
            Set<Long> value4Set = paasRedisHelper.getValue4Set(RedisPrefixConstant.CLUE_AUTO_ALLOT, corpid);
            if (CollectionsUtil.isEmpty(value4Set)) {
                value4Set = new HashSet<>();
            }
            value4Set.addAll(dataIds);
            Integer expireTime = TimeConstant.SECONDS_PER_MINUTE * 30;
            paasRedisHelper.setValue4Set(RedisPrefixConstant.CLUE_AUTO_ALLOT, corpid, value4Set, expireTime);

            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();

            boolQueryBuilder.filter(termQuery(ClueEnum.getEsAttr4Keyword(ClueEnum.IS_PUBLIC), BasicConstant.ONE));
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termsQuery("dataId", dataIds));
            boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.PASS.getType(), FlowStatusEnum.NOT_NEED_APPROVAL.getType())));
            // 因为下面匹配筛选条件那里要拿很多字段，所以这边就不限制查询字段了
            //设置查询路由
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            searchRequest.source(sourceBuilder);
            sourceBuilder.query(boolQueryBuilder);
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, dataIds.size());
            XbbAggregatedPage<PaasFormDataEntityExt> xbbAggregatedPage = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
            resultList = xbbAggregatedPage.getContent();
            if (CollectionsUtil.isEmpty(resultList)) {
                return;
            }
            Map<Long, Set<String>> ownerMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (hasOwnerFilter) {
                // 获取前负责人的团队数据
                SearchSourceBuilder teamSourceBuilder = new SearchSourceBuilder();
                BoolQueryBuilder filter = boolQuery()
                        .filter(termQuery("corpid.keyword", corpid))
                        .filter(termQuery(ClueTeamEnum.getEsAttr(ClueTeamEnum.IS_MAIN), 1))
                        .filter(termQuery("del", -1))
                        .filter(termsQuery(ClueTeamEnum.getEsAttr(ClueTeamEnum.DATA_ID), dataIds));

                //拿固定数据
                teamSourceBuilder.fetchSource(new String[]{ClueTeamEnum.getAttrConnectData(ClueTeamEnum.DATA_ID), ClueTeamEnum.getAttrConnectData(ClueTeamEnum.USER_ID)},null);
                filter.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_CLUE_TEAM.getType()));
                teamSourceBuilder.query(filter);
                SearchRequest teamSearchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_CLUE_TEAM.getIndex());
                PageRequest teamPageRequest = EsUtil.setPage(teamSourceBuilder, 1, 10000);
                teamSearchRequest.source(teamSourceBuilder);
                XbbAggregatedPage<PaasFormDataEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(teamPageRequest,teamSearchRequest, PaasFormDataEntity.class);
                List<ClueUserEntity> content =(List<ClueUserEntity>) transferSubFormHelper.transferFormDataToUserTeamList(IndexTypeEnum.IDX_SAAS_CLUE_TEAM, esEntities.getContent());
                for(ClueUserEntity clueUserEntity : content) {
                    Long clueId = clueUserEntity.getDataId();
                    String userId = clueUserEntity.getUserId();
                    Set<String> orDefault = ownerMap.getOrDefault(clueId, new HashSet<>());
                    orDefault.add(userId);
                    ownerMap.put(clueId, orDefault);
                }

            }
            Map<String, List<PaasFormDataEntityExt>> userAndClueMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PaasFormDataEntityExt entityExt : resultList) {
                Long dataFormId = entityExt.getFormId();
                for (ClueAutoAllocationEntity entity : entitys) {
                    if (!Objects.equals(dataFormId, entity.getFormId())) {
                        //该数据不等于该表单，该规则不处理
                        continue;
                    }
                    List<ConditionsEntityExt> jsonArray = JSON.parseArray(JSON.toJSONString(entity.getJsonData()), ConditionsEntityExt.class);
                    boolean isMatch = false;
                    for (ConditionsEntityExt conditionsEntityExt : jsonArray) {
                        isMatch = matchFilter(conditionsEntityExt, entityExt, ownerMap);
                        if (!isMatch) {
                            break;
                        }
                    }
                    if (!isMatch) {
                        continue;
                    }
                    boolean limit = (Objects.equals(entity.getDistributionLimit(), 1) && Objects.nonNull(maxRule) && Objects.equals(maxRule.getStatus(), 1));
                    // 将线索分配给用户
                    String userId = allotClue2User(null, entity, entityExt, userEntityMap, limit, maxRule, userAndClueMap, false);
                    if (StringUtil.isNotEmpty(userId)) {
                        break;
                    }
                }
            }
            Long now = DateTimeUtil.getInt();
            List<ClueUserEntity> addBatchList = new ArrayList<>();
            List<Long> updateIds = new ArrayList<>();
            List<String> clueNameList;
            String name;
            Map<UserEntity, List<String>> clueIdAndName = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, Integer> numMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (Map.Entry<String, List<PaasFormDataEntityExt>> entry : userAndClueMap.entrySet()) {

                UserEntity userEntity = userEntityMap.get(entry.getKey());
                List<PaasFormDataEntityExt> value = entry.getValue();

                clueNameList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Integer i = 0;
                List<Long> hasAddDataIdList = new ArrayList<>();
                for (PaasFormDataEntityExt item : value){
                    if (hasAddDataIdList.contains(item.getDataId())) {
                        continue;
                    }
                    ClueUserEntity clueUserEntity = new ClueUserEntity();
                    clueUserEntity.setCorpid(corpid);
                    clueUserEntity.setUserId(userEntity.getUserId());
                    clueUserEntity.setUserName(userEntity.getName());
                    clueUserEntity.setUserAvatar(userEntity.getAvatar());
                    clueUserEntity.setDataId(item.getDataId());
                    clueUserEntity.setDistributionTime(now);
                    clueUserEntity.setIsMain(1);
                    addBatchList.add(clueUserEntity);
                    hasAddDataIdList.add(item.getDataId());
                    updateIds.add(item.getDataId());

                    name = FastJsonHelper.getStringOrDefaultFromFormData(item.getData(), ClueEnum.COMPANY_NAME.getAttr(), "");
                    if (i < 200) {
                        clueNameList.add(name);
                    }
                    i++;
                }
                if (Objects.nonNull(userEntity)) {
                    clueIdAndName.put(userEntity, clueNameList);
                    numMap.put(entry.getKey(), i);
                }
            }
            if (CollectionsUtil.isNotEmpty(updateIds)) {
                Map<String, Object> updateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                updateMap.put(ClueEnum.DISTRIBUTION_DATE.getAttr(), DateTimeUtil.getInt());
                updateMap.put(ClueEnum.IS_PUBLIC.getAttr(), PublicEnum.NON_PUBLIC.getCode());
                clueModel.updateBatchNoSub(corpid, updateIds, updateMap, WriteRequest.RefreshPolicy.WAIT_UNTIL);
            }
            if (CollectionsUtil.isNotEmpty(addBatchList)) {
                clueUserModel.insertBatch(addBatchList);
            }
            if (pushMessage) {
                String pushUserStr = "系统自动";
                for (Map.Entry<String, List<PaasFormDataEntityExt>> entry : userAndClueMap.entrySet()) {
                    List<PaasFormDataEntityExt> value = entry.getValue();
                    if(CollectionsUtil.isNotEmpty(value) && Objects.nonNull(value.get(0))){
                        PaasFormDataEntityExt entityExt = value.get(0);
                        List<Long> clueDataIds = value.stream().map(PaasFormDataEntityExt::getDataId).collect(Collectors.toList());
                        PushRefTypePojo.Options options = new PushRefTypePojo.Options(entityExt.getAppId(), entityExt.getMenuId(), entityExt.getFormId(), null, clueDataIds, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CLUE.getCode(), XbbRefTypeEnum.ALL_CLUE.getCode());
                        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, Arrays.asList(entry.getKey()), Arrays.asList(entityExt.getDataId()), 0, null, I18nMessageUtil.getMessage(CluePushConstant.CLUE_DISTRIBUTION_TITLE), String.format(I18nMessageUtil.getMessage(CluePushConstant.CLUE_DISTRIBUTION_CONTENT), pushUserStr, value.size()), null, options);
                        baseProducer.sendMessage(PushTypeEnum.CLUE_DISTRIBUTION_PUSH, messageRabbitMqDTO);
                    }
                }
            }
            paasRedisHelper.removeValue(RedisPrefixConstant.CLUE_AUTO_ALLOT, corpid);
            LOG.info("是否需要更新自动分配规则userAndClueMap.isEmpty:"+userAndClueMap.isEmpty());
            if (!userAndClueMap.isEmpty()) {
                List<ClueAutoAllocationEntity> updateEntitys = new ArrayList<>();
                for (ClueAutoAllocationEntity entity : entitys) {
                    ClueAutoAllocationEntity allocationEntity = new ClueAutoAllocationEntity();
                    allocationEntity.setId(entity.getId());
                    allocationEntity.setAllocationSurplusType(entity.getAllocationSurplusType());
                    allocationEntity.setAllocationSurplus(entity.getAllocationSurplus());
                    updateEntitys.add(allocationEntity);
                }
                // 更新剩余没有分配完的规则
                LOG.info("updateBatchSursplus更新剩余没有分配完的规则corpid:"+corpid);
                clueAutoAllocationModel.updateBatchSursplus(updateEntitys, corpid);
            }
            
            // 日志
            if(!clueIdAndName.isEmpty()){
                String clueNameStr;
                Integer num;
                for (Map.Entry<UserEntity, List<String>> entry : clueIdAndName.entrySet()) {
                    UserEntity userEntity = entry.getKey();
                    List<String> value = entry.getValue();
                    num = numMap.get(userEntity.getUserId());
                    clueNameStr = StringUtils.join(value, "，");
                    if (num > 200) {
                        clueNameStr = clueNameStr + " 等" + num + "条线索";
                    }

                    String distributionName = userEntity.getName();

                    if (value.size() > 1) {
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_ADMIN_BATCH_DISTRIBUTION_CLUE), distributionName, value.size());
                        List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        InfoArrPojo infoArrPojo = new InfoArrPojo();
                        infoArrPojo.setTitle(ClueEnum.COMPANY_NAME.getAttrName());
                        infoArrPojo.setContent(clueNameStr);
                        infoArrPojoList.add(infoArrPojo);
                        mongoLogHelp.buildLog4InfoArrWithoutAsync(infoArrPojoList, corpid, PaasConstant.SYS_USER_ID, I18nMessageUtil.getMessage(PaasConstant.SYS_OPERATING), OperateModuleTypeEnum.CLUE, OperateTypeEnum.DISTRIBUTE, "", "", memo, "");
                    } else if (Objects.equals(value.size(), 1)) {
                        String clueId = userAndClueMap.get(userEntity.getUserId()).get(0).toString();
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_ADMIN_DISTRIBUTION_CLUE), clueNameStr, distributionName);
                        mongoLogHelp.buildLogWithoutAsync(corpid, PaasConstant.SYS_USER_ID, I18nMessageUtil.getMessage(PaasConstant.SYS_OPERATING), OperateModuleTypeEnum.CLUE, OperateTypeEnum.DISTRIBUTE, clueId, clueNameStr, memo, "");
                    }
                }
            }
        } catch (Exception e) {
            LOG.error("AutoClueAssignmentRabbitServiceImpl.autoClueAssignment出现了异常, corpid:" + corpid, e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001,"AutoClueAssignmentRabbitServiceImpl.autoClueAssignment出现了异常, corpid"+corpid);
        }
    }

    private boolean matchFilter(ConditionsEntityExt conditionsEntityExt, PaasFormDataEntityExt entityExt, Map<Long, Set<String>> ownerMap) {
        boolean matchFIlter = false;
        String corpid = entityExt.getCorpid();
        Long dataId = entityExt.getDataId();
        Integer fieldType = conditionsEntityExt.getFieldType();
        String symbol = conditionsEntityExt.getSymbol();
        String attr = conditionsEntityExt.getAttr();
        String value = entityExt.getData().getString(attr);
        List<String> addressAlias = AddressEnum.getAliasList();
        if (addressAlias.contains(attr)) {
            JSONObject jsonObject = entityExt.getData().getJSONObject(ClueEnum.ADDRESS.getAttr());
            if (Objects.nonNull(jsonObject)) {
                value = jsonObject.getString(attr);
            }
            // 本来地址这边的fieldType是20029，现在强行转为1
            fieldType = FieldTypeEnum.TEXT.getType();
        }
        if (Objects.equals(fieldType, FieldTypeEnum.ADDTIME.getType())) {
            value = entityExt.getAddTime().toString();
        } else if (Objects.equals(fieldType, FieldTypeEnum.UPDATETIME.getType())) {
            value = entityExt.getUpdateTime().toString();
        } else if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
            value = entityExt.getSerialNo();
        } else if (Objects.equals(fieldType, FieldTypeEnum.CREATORID.getType())) {
            value = entityExt.getCreatorId();
        }
        List<String> conditionValueStr = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(conditionsEntityExt.getValue())) {
            conditionsEntityExt.getValue().forEach(item -> conditionValueStr.add(item.toString()));
        }
        try {
            // 日期字段动态值进行时间转换
            if (Objects.equals(symbol, ConditionEnum.DYNAMIC.getSymbol()) && Objects.equals(fieldType, FieldTypeEnum.DATETIME.getType())) {
                EsUtil.getValueByDate(conditionsEntityExt);
            }
        } catch (XbbException e) {
            return matchFIlter;
        }
        ConditionEnum conditionEnum = ConditionEnum.getConditionEnum(symbol);
        switch (conditionEnum) {
            case EMPTY:
                if (Objects.equals(fieldType, FieldTypeEnum.LABEL.getType())) {
                    matchFIlter = true;
                    List<Long> labelIds = getLabelIds(value, corpid);
                    if (CollectionsUtil.isNotEmpty(labelIds)) {
                        matchFIlter = false;
                    }
                } else if (Objects.equals(fieldType, FieldTypeEnum.CHECKBOX_GROUP.getType())
                        || Objects.equals(fieldType, FieldTypeEnum.COMBO_CHECK.getType())
                        || Objects.equals(fieldType, FieldTypeEnum.USER_GROUP.getType())
                        || Objects.equals(fieldType, FieldTypeEnum.DEPT_GROUP.getType())) {
                    if (StringUtil.isEmpty(value) || Objects.equals(value, "[]")) {
                        matchFIlter = true;
                    }
                } else {
                    if (StringUtil.isEmpty(value)) {
                        matchFIlter = true;
                    }
                }
                break;
            case NOEMPTY:
                if (Objects.equals(fieldType, FieldTypeEnum.LABEL.getType())) {
                    List<Long> labelIds = getLabelIds(value, corpid);
                    if (CollectionsUtil.isNotEmpty(labelIds)) {
                        matchFIlter = true;
                    }
                }  else if (Objects.equals(fieldType, FieldTypeEnum.COMBO_CHECK.getType())
                        || Objects.equals(fieldType, FieldTypeEnum.USER_GROUP.getType())
                        || Objects.equals(fieldType, FieldTypeEnum.DEPT_GROUP.getType())) {
                    if (StringUtil.isNotEmpty(value) && !Objects.equals(value, "[]")) {
                        matchFIlter = true;
                    }
                } else {
                    if (StringUtil.isNotEmpty(value)) {
                        matchFIlter = true;
                    }
                }
                break;
            case EQUAL:
                if (Objects.equals(fieldType, FieldTypeEnum.LABEL.getType())) {
                    List<Long> labelIds = getLabelIds(value, corpid);
                    for (String o : conditionValueStr) {
                        Long oLong = Long.valueOf(o);
                        if (labelIds.contains(oLong)) {
                            matchFIlter = true;
                            break;
                        }
                    }
                } else if (Objects.equals(fieldType, FieldTypeEnum.OWNERID.getType())) {
                    Set<String> orDefault = ownerMap.getOrDefault(dataId, new HashSet<>());
                    if (orDefault.contains(conditionValueStr.get(0))) {
                        matchFIlter = true;
                    }
                } else if (Objects.equals(fieldType, FieldTypeEnum.COMBO_CHECK.getType())
                        || Objects.equals(fieldType, FieldTypeEnum.USER_GROUP.getType())
                        || Objects.equals(fieldType, FieldTypeEnum.CHECKBOX_GROUP.getType())
                        || Objects.equals(fieldType, FieldTypeEnum.DEPT_GROUP.getType())) {
                    if (StringUtil.isNotEmpty(value) && !Objects.equals(value, "[]")) {
                        List<String> longs = JSONArray.parseArray(value, String.class);
                        longs.retainAll(conditionValueStr);
                        if (CollectionsUtil.isNotEmpty(longs)) {
                            matchFIlter = true;
                        }
                    }
                } else {
                    if (Objects.equals(value, conditionValueStr.get(0))) {
                        matchFIlter = true;
                    }
                }
                break;
            case NOEQUAL:
                if (!Objects.equals(value, conditionValueStr.get(0))) {
                    matchFIlter = true;
                }
                break;
            case LESSTHAN:
                if (StringUtil.isNotEmpty(value)) {
                    BigDecimal valueDecimal;
                    BigDecimal startDecimal;
                    try {
                        valueDecimal = new BigDecimal(value);
                        startDecimal = new BigDecimal(conditionValueStr.get(0));
                    } catch (Exception e) {
                        //不能"转成BigDecimal时返回空
                        LOG.error("AutoClueAssignmentRabbitServiceImpl.matchFilter转换类型错误,value=" + value + "   conditionValueStr=" + conditionValueStr.toString(), e);
                        break;
                    }
                    if (valueDecimal.compareTo(startDecimal) == -1) {
                        matchFIlter = true;
                    }
                }
                break;
            case LESSEQUAL:
                if (StringUtil.isNotEmpty(value)) {
                    BigDecimal valueDecimal;
                    BigDecimal startDecimal;
                    try {
                        valueDecimal = new BigDecimal(value);
                        startDecimal = new BigDecimal(conditionValueStr.get(0));
                    } catch (Exception e) {
                        //不能"转成BigDecimal时返回空
                        LOG.error("AutoClueAssignmentRabbitServiceImpl.matchFilter转换类型错误,value=" + value + "   conditionValueStr=" + conditionValueStr.toString(), e);
                        break;
                    }
                    if (valueDecimal.compareTo(startDecimal) < 1) {
                        matchFIlter = true;
                    }
                }
                break;
            case GREATERTHAN:
                if (StringUtil.isNotEmpty(value)) {
                    BigDecimal valueDecimal;
                    BigDecimal startDecimal;
                    try {
                        valueDecimal = new BigDecimal(value);
                        startDecimal = new BigDecimal(conditionValueStr.get(0));
                    } catch (Exception e) {
                        //不能"转成BigDecimal时返回空
                        LOG.error("AutoClueAssignmentRabbitServiceImpl.matchFilter转换类型错误,value=" + value + "   conditionValueStr=" + conditionValueStr.toString(), e);
                        break;
                    }
                    if (valueDecimal.compareTo(startDecimal) == 1) {
                        matchFIlter = true;
                    }
                }
                break;
            case GREATEREQUAL:
                if (StringUtil.isNotEmpty(value)) {
                    BigDecimal valueDecimal;
                    BigDecimal startDecimal;
                    try {
                        valueDecimal = new BigDecimal(value);
                        startDecimal = new BigDecimal(conditionValueStr.get(0));
                    } catch (Exception e) {
                        //不能"转成BigDecimal时返回空
                        LOG.error("AutoClueAssignmentRabbitServiceImpl.matchFilter转换类型错误,value=" + value + "   conditionValueStr=" + conditionValueStr.toString(), e);
                        break;
                    }
                    if (valueDecimal.compareTo(startDecimal) > -1) {
                        matchFIlter = true;
                    }

                }
                break;
            case ALLINCLUDE:
                if (Objects.equals(fieldType, FieldTypeEnum.OWNERID.getType())) {
                    Set<String> orDefault = ownerMap.getOrDefault(dataId, new HashSet<>());
                    if (orDefault.contains(conditionValueStr.get(0))) {
                        matchFIlter = true;
                    }
                } else {
                    if (StringUtil.isNotEmpty(value) && !Objects.equals(value, "[]")) {
                        List<String> longs = JSONArray.parseArray(value, String.class);
                        longs.retainAll(conditionValueStr);
                        if (Objects.equals(longs.size(), conditionValueStr.size())) {
                            matchFIlter = true;
                        }
                    }
                }
                break;
            case INCLUDE:
                if (StringUtil.isNotEmpty(value) && !Objects.equals(value, "[]")) {
                    List<String> longs = JSONArray.parseArray(value, String.class);
                    longs.retainAll(conditionValueStr);
                    if (CollectionsUtil.isNotEmpty(longs)) {
                        matchFIlter = true;
                    }
                }
                break;
            case LIKE:
                if (StringUtil.isEmpty(value) || conditionValueStr.isEmpty()) {
                    break;
                }
                if (value.indexOf(conditionValueStr.get(0)) != -1) {
                    matchFIlter = true;
                }
                break;
            case NOLIKE:
                if (StringUtil.isEmpty(value)) {
                    matchFIlter = true;
                    break;
                }
                if (value.indexOf(conditionValueStr.get(0)) == -1) {
                    matchFIlter = true;
                }
                break;
            case IN:
                if (StringUtil.isEmpty(value) || conditionValueStr.isEmpty()) {
                    break;
                }
                for (String o : conditionValueStr) {
                    if (Objects.equals(o, value)) {
                        matchFIlter = true;
                        break;
                    }
                }
                break;
            case NOIN:
                matchFIlter = true;
                if (StringUtil.isEmpty(value)) {
                    break;
                }
                for (String o : conditionValueStr) {
                    if (Objects.equals(o, value)) {
                        matchFIlter = false;
                        break;
                    }
                }
                break;
            case RANGE:
            case DYNAMIC:
                if (StringUtil.isEmpty(value) && conditionValueStr.size() > 1) {
                    break;
                }
                BigDecimal valueDecimal;
                BigDecimal startDecimal;
                BigDecimal endDecimal;
                try {
                    valueDecimal = new BigDecimal(value);
                    startDecimal = new BigDecimal(conditionValueStr.get(0));
                    endDecimal = new BigDecimal(conditionValueStr.get(1));
                } catch (Exception e) {
                    //不能"转成BigDecimal时返回空
                    LOG.error("AutoClueAssignmentRabbitServiceImpl.matchFilter转换类型错误,value=" + value + "   conditionValueStr=" + conditionValueStr.toString(), e);
                    break;
                }
                if (valueDecimal.compareTo(startDecimal) > -1 && valueDecimal.compareTo(endDecimal) == -1) {
                    matchFIlter = true;
                }
                break;
            default:
                break;
        }
        return matchFIlter;
    }

    private List<Long> getLabelIds(String value, String corpid) {
        List<Long> labelIds = new ArrayList<>();
        if (StringUtil.isNotEmpty(value)) {
            List<Long> ids = JSONArray.parseArray(value, Long.class);
            if (CollectionsUtil.isNotEmpty(ids)) {
                List<LabelEntity> byLabelIds = labelModel.getByLabelIds(ids, corpid);
                if (CollectionsUtil.isNotEmpty(byLabelIds)) {
                    byLabelIds.forEach(item -> labelIds.add(item.getId()));
                }
            }
        }
        return labelIds;
    }


    public void addressSearchCondition(List<ConditionsEntityExt> conditions) {
        List<ConditionsEntityExt> publicGroupAddressConditions = new ArrayList<>();
        Iterator<ConditionsEntityExt> iterator = conditions.iterator();
        while (iterator.hasNext()){
            ConditionsEntityExt entityExt = iterator.next();
            // 公海池分组：省、市、区
            if(Objects.equals(PaasConstant.PROVINCE, entityExt.getAttr()) || Objects.equals(PaasConstant.CITY, entityExt.getAttr())
                    || Objects.equals(PaasConstant.DISTRICT, entityExt.getAttr())) {
                List<Object> value = entityExt.getValue();
                String subAttr = entityExt.getAttr();
                String symbol = entityExt.getSymbol();
                Integer fieldType = FieldTypeEnum.TEXT.getType();
                String attr = ClueEnum.ADDRESS.getAttr() + StringConstant.POINT + subAttr;
                ConditionEnum conditionEnum = ConditionEnum.getConditionEnum(entityExt.getSymbol());
                if(Objects.isNull(conditionEnum)) {
                    continue;
                }
                switch (conditionEnum) {
                    case EQUAL:
                    case NOEQUAL:
                    case LIKE:
                    case NOLIKE:
                    case IN:
                    case NOIN:
                        ConditionsEntityExt hasValueCondition = new ConditionsEntityExt(attr, "", fieldType, symbol, value);
                        publicGroupAddressConditions.add(hasValueCondition);
                        break;
                    case EMPTY:
                    case NOEMPTY:
                        ConditionsEntityExt noValueCondition = new ConditionsEntityExt(attr, "", fieldType, symbol, Collections.singletonList(""));
                        publicGroupAddressConditions.add(noValueCondition);
                        break;
                    default:
                        break;
                }
                iterator.remove();
            }
        }
        conditions.addAll(publicGroupAddressConditions);
    }

    private String allotClue2uer(PaasFormDataEntityExt clueEntity, ClueAutoAllocationEntity entity, Map<String, UserEntity> userMap,
                                  ClueRuleEntity maxRule, Map<String, List<PaasFormDataEntityExt>> userAndClueMap) throws XbbException{
        String userId = commonAllot(entity, userMap);
        if (StringUtil.isNotEmpty(userId)) {
            List<PaasFormDataEntityExt> orDefault = userAndClueMap.getOrDefault(userId, new ArrayList<>());
            if (Objects.equals(entity.getDistributionLimit(), 1) && Objects.nonNull(maxRule) && Objects.equals(maxRule.getStatus(), 1)) {
                UserEntity userEntity = userMap.get(userId);
                Map<Long, PaasFormDataEntityExt> entityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                entityMap.put(clueEntity.getDataId(), clueEntity);
                for (PaasFormDataEntityExt entityExt : orDefault) {
                    entityMap.put(entityExt.getDataId(), entityExt);
                }
                String errorMsg = userTeamService.canGainMaxClueNum(maxRule, entity.getCorpid(), userEntity, entityMap);
                if (StringUtil.isNotEmpty(errorMsg)) {
                    userId = null;
                    // 如果当前人超出最大拥有线索数规则，那么需要依次判断下面的人是否符合条件，直到该规则人员判断完毕
                    JSONArray allocationSurplus = entity.getAllocationSurplus();
                    while (true) {
                        if ((Objects.isNull(allocationSurplus) || allocationSurplus.isEmpty()) && Objects.equals(entity.getSurplusFlag(), 0)) {
                            break;
                        }
                        userId = commonAllot(entity, userMap);
                        if (StringUtil.isNotEmpty(userId)) {
                            userEntity = userMap.get(userId);
                            orDefault = userAndClueMap.getOrDefault(userId, new ArrayList<>());
                            Map<Long, PaasFormDataEntityExt> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            map.put(clueEntity.getDataId(), clueEntity);
                            for (PaasFormDataEntityExt entityExt : orDefault) {
                                map.put(entityExt.getDataId(), entityExt);
                            }
                            errorMsg = userTeamService.canGainMaxClueNum(maxRule, entity.getCorpid(), userEntity, map);
                            if (StringUtil.isEmpty(errorMsg)) {
                                // 也要判断一下是否超最大拥有线索数，如果没超，就代表这条数据给了他并且跳出循环；如果超了，就继续循环该规则剩余的人
                                break;
                            } else {
                                userId = null;
                            }
                        }

                    }
                }
            }
            if (StringUtil.isNotEmpty(userId)) {
                orDefault = userAndClueMap.getOrDefault(userId, new ArrayList<>());
                orDefault.add(clueEntity);
                userAndClueMap.put(userId, orDefault);
            }
        }
        return userId;
    }

    private String commonAllot(ClueAutoAllocationEntity entity, Map<String, UserEntity> userMap) {
        String userId = null;
        Integer surplustype = entity.getAllocationSurplusType();
        JSONArray surplusJsonArray = entity.getAllocationSurplus();
        List<Integer> numList = entity.getNumList();
        if (Objects.isNull(surplusJsonArray) || surplusJsonArray.isEmpty()) {
            for (Map.Entry<Integer, Map<List<String>, Integer>> entry : entity.getAllocationValueMap().entrySet()) {
                surplustype = entry.getKey();
                if (Objects.equals(entity.getSurplusFlag(), 0) && Objects.equals(surplustype, ClueAutoDistributTypeEnum.NUMBER_ASSIGNED.getType())) {
                    // 如果数量分配，且正常的数量已经分配完了，那么该规则不会触发了
                    return null;
                }
                surplusJsonArray = new JSONArray();
                for (Map.Entry<List<String>, Integer> subEntry : entry.getValue().entrySet()) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("user", subEntry.getKey());
                    jsonObject.put("num", subEntry.getValue());
                    surplusJsonArray.add(jsonObject);
                }
                break;
            }
            entity.setSurplusFlag(0);
        }
        Iterator<Object> iterator1 = surplusJsonArray.iterator();
        while (iterator1.hasNext()) {
            JSONObject obj = (JSONObject) iterator1.next();
            List<Object> userIds;
            Integer num = null;
            try {
                userIds = obj.getJSONArray("user");
                num = obj.getInteger("num");
            } catch (JSONException e) {
                userIds = new ArrayList<>();
            }
            if (CollectionsUtil.isEmpty(userIds)) {
                continue;
            }
            // 过滤离职人员
            userIds.removeIf(item -> !userMap.containsKey(item.toString()));
            if (CollectionsUtil.isEmpty(userIds)) {
                iterator1.remove();
                continue;
            }
            Iterator<Object> iterator = userIds.iterator();
            while (iterator.hasNext()) {
                String next = iterator.next().toString();
                if (!Objects.equals(surplustype, ClueAutoDistributTypeEnum.ONLY_ASSIGNED.getType())) {
                    userId = next;
                    if (Objects.nonNull(num) && num > 0) {
                        num--;
                        if (Objects.equals(num, 0)) {
                            iterator.remove();
                        }
                    } else {
                        iterator.remove();
                    }
                    break;
                } else {
                    userId = next;
                    iterator.remove();
                }
            }
            if (CollectionsUtil.isEmpty(userIds)) {
                iterator1.remove();
                break;
            }
            obj.put("user", userIds);
            if (Objects.nonNull(num) && num > 0) {
                obj.put("num", num);
            }
            if (Objects.equals(num, 0) && CollectionsUtil.isNotEmpty(numList)) {
                // 如果同规则里，一个人的数量分完了，那么，就需要再拿一遍这个规则的数量
                int i = numList.size() - surplusJsonArray.size();
                obj.put("num", numList.get(i));
            }
            break;
        }
        entity.setAllocationSurplusType(surplustype);
        entity.setAllocationSurplus(surplusJsonArray);
        return userId;
    }

    /**
     * 将线索分配给用户
     * @param uId
     * @param entity 线索自动分配实体
     * @param clueEntity 线索数据
     * @param userMap 用户实体
     * @param limit
     * @param maxRule
     * @param userAndClueMap
     * @param innerLoop
     * @return
     * @throws XbbException
     */
    private String allotClue2User(String uId, ClueAutoAllocationEntity entity, PaasFormDataEntityExt clueEntity, Map<String, UserEntity> userMap, boolean limit, ClueRuleEntity maxRule,
                                  Map<String, List<PaasFormDataEntityExt>> userAndClueMap, boolean innerLoop) throws XbbException {
        Integer surplustype = entity.getAllocationSurplusType();
        JSONArray surplusJsonArray = entity.getAllocationSurplus();
        if (Objects.isNull(surplusJsonArray) || surplusJsonArray.isEmpty()) {
            // 分配剩余人员
            for (Map.Entry<Integer, Map<List<String>, Integer>> entry : entity.getAllocationValueMap().entrySet()) {
                surplustype = entry.getKey();
                /*if (Objects.equals(entity.getSurplusFlag(), 0) && Objects.equals(surplustype, ClueAutoDistributTypeEnum.NUMBER_ASSIGNED.getType())) {
                    // 如果数量分配，且正常的数量已经分配完了，那么该规则不会触发了
                    return null;
                }*/
                surplusJsonArray = new JSONArray();
                for (Map.Entry<List<String>, Integer> subEntry : entry.getValue().entrySet()) {
                    for (String userId : subEntry.getKey()) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("user", userId);
                        jsonObject.put("num", subEntry.getValue());
                        surplusJsonArray.add(jsonObject);
                    }
                }
                break;
            }
            entity.setSurplusFlag(0);
        }
        List<PaasFormDataEntityExt> orDefault = new ArrayList<>();
        if (innerLoop) {
            uId = getUserId(uId, surplusJsonArray, userMap, limit, userAndClueMap, clueEntity, maxRule, surplustype, orDefault);
            if (StringUtil.isEmpty(uId)) {
                Map<String, Integer> userAndNumMap = new LinkedHashMap<>();
                if (!surplusJsonArray.isEmpty()) {
                    for (int i = 0; i < surplusJsonArray.size(); i++) {
                        JSONObject obj = surplusJsonArray.getJSONObject(i);
                        String userId = obj.getString("user");
                        Integer num = obj.getInteger("num");
                        if (StringUtil.isNotEmpty(userId)) {
                            userAndNumMap.put(userId, num);
                        }
                    }
                }
                JSONArray arr = new JSONArray();
                for (Map.Entry<Integer, Map<List<String>, Integer>> entry : entity.getAllocationValueMap().entrySet()) {
                    for (Map.Entry<List<String>, Integer> subEntry : entry.getValue().entrySet()) {
                        for (String userId : subEntry.getKey()) {
                            Integer num = subEntry.getValue();
                            if (Objects.isNull(num)) {
                                num = 1;
                            }
                            if (userAndNumMap.containsKey(userId)) {
                                Integer suplusNum = userAndNumMap.get(userId);
                                //上一次剩余的数量加上这次得到数量
                                if (Objects.nonNull(suplusNum)) {
                                    num += suplusNum;
                                } else {
                                    // 如果suplusNum为null，那么就是循环分配，上一次分配剩余加上新一轮
                                    num++;
                                }
                            }
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("user", userId);
                            jsonObject.put("num", num);
                            arr.add(jsonObject);
                        }
                    }
                    break;
                }
                surplusJsonArray = arr;
                uId = getUserId(uId, surplusJsonArray, userMap, limit, userAndClueMap, clueEntity, maxRule, surplustype, orDefault);
            }
        } else {
            uId = getUserId(uId, surplusJsonArray, userMap, limit, userAndClueMap, clueEntity, maxRule, surplustype, orDefault);
        }
        if (StringUtil.isEmpty(uId)){
            if (innerLoop) {
                return uId;
            }
            return allotClue2User(uId, entity, clueEntity, userMap, limit,maxRule, userAndClueMap, true);
        }
         entity.setAllocationSurplusType(surplustype);
        entity.setAllocationSurplus(surplusJsonArray);
        return uId;
    }

    /**
     * 获取用户id
     * @param uId
     * @param surplusJsonArray
     * @param userMap
     * @param limit
     * @param userAndClueMap
     * @param clueEntity
     * @param maxRule
     * @param surplustype
     * @param orDefault
     * @return
     * @throws XbbException
     */
    private String getUserId(String uId, JSONArray surplusJsonArray, Map<String, UserEntity> userMap, boolean limit, Map<String, List<PaasFormDataEntityExt>> userAndClueMap, PaasFormDataEntityExt clueEntity, ClueRuleEntity maxRule, Integer surplustype, List<PaasFormDataEntityExt> orDefault) throws XbbException{
        Iterator<Object> iterator = surplusJsonArray.iterator();
        while (iterator.hasNext()) {
            JSONObject obj = (JSONObject) iterator.next();
            String userId = obj.getString("user");
            Integer num = obj.getInteger("num");

            if (StringUtil.isEmpty(userId)) {
                continue;
            }
            if (!userMap.containsKey(userId)) {
                iterator.remove();
                continue;
            }
            orDefault = userAndClueMap.getOrDefault(userId, new ArrayList<>());
            if (limit) {
                UserEntity userEntity = userMap.get(userId);
                Map<Long, PaasFormDataEntityExt> entityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                entityMap.put(clueEntity.getDataId(), clueEntity);
                for (PaasFormDataEntityExt entityExt : orDefault) {
                    entityMap.put(entityExt.getDataId(), entityExt);
                }
                String errorMsg = userTeamService.canGainMaxClueNum(maxRule, maxRule.getCorpid(), userEntity, entityMap);
                if (StringUtil.isEmpty(errorMsg)) {
                    uId = userId;
                    if (!Objects.equals(surplustype, ClueAutoDistributTypeEnum.ONLY_ASSIGNED.getType())) {
                        if (Objects.nonNull(num) && num > 0) {
                            num--;
                            if (Objects.equals(num, 0)) {
                                iterator.remove();
                            } else {
                                obj.put("num", num);
                            }
                        } else {
                            iterator.remove();
                        }
                        break;
                    } else {
                        iterator.remove();
                    }
                    break;
                }
            } else {
                uId = userId;
                if (!Objects.equals(surplustype, ClueAutoDistributTypeEnum.ONLY_ASSIGNED.getType())) {
                    if (Objects.nonNull(num) && num > 0) {
                        num--;
                        if (Objects.equals(num, 0)) {
                            iterator.remove();
                        } else {
                            obj.put("num", num);
                        }
                    } else {
                        iterator.remove();
                    }
                    break;
                } else {
                    iterator.remove();
                }
                break;
            }
        }
        if (StringUtil.isNotEmpty(uId)) {
            orDefault.add(clueEntity);
            userAndClueMap.put(uId, orDefault);
        }
        return uId;
    }
}
